#include "KThread.h"
#include <process.h>
#include "KDebug.h"

KThread::KThread() : m_thread(NULL), m_priority(THREAD_PRIORITY_NORMAL)
{
}

KThread::~KThread()
{
    if (m_thread) {
        CloseHandle(m_thread);
    }
}

DWORD KThread::exitCode() const
{
    DWORD ret = 0;
    if (m_thread && !GetExitCodeThread(m_thread, &ret)) {
        KDebugLib("GetExitCodeThread() failed: %d", GetLastError());
    }
    return ret;
}

bool KThread::isRunning() const
{
    return exitCode() == STILL_ACTIVE;
}

int KThread::priority() const
{
    if (m_thread) {
        return GetThreadPriority(m_thread);
    }
    return m_priority;
}

bool KThread::setPriority(int nPriority)
{
    if (m_thread) {
        return !!SetThreadPriority(m_thread, nPriority);
    }
    m_priority = nPriority;
    return true;
}

void KThread::start()
{
    if (!isRunning()) {
        if (m_thread) {
            CloseHandle(m_thread);
        }
        m_thread = reinterpret_cast<HANDLE>(
            _beginthreadex(NULL, 0, KThread::ThreadProc, static_cast<KThread *>(this), 0, NULL)
        );
        assert(m_thread != NULL);
        if (m_priority != THREAD_PRIORITY_NORMAL) {
            setPriority(m_priority);
        }
    }
}

bool KThread::wait(DWORD ms)
{
    if (m_thread) {
        return WaitForSingleObject(m_thread, ms) == WAIT_OBJECT_0;
    }
    return true;
}

unsigned WINAPI KThread::ThreadProc(void *lpThread)
{
    assert(lpThread != NULL);
    KThread *lpThis = static_cast<KThread *>(lpThread);
    return lpThis->run();
}